/*
 * CreateDatabase.cpp
 *

 */

#include "CreateDatabase.h"
#include "../BufferManager/BufferManager.h"
#include "../PageLayout/DBMetaData.h"
#include "../dependency/debug.h"
#include "../PageLayout/DirHeader.h"
#include "../Sysfiles/SysCatalog.h"
#include "../PageLayout/FreePageLinkedList.h"
#include "../dependency/ExternDefsOfGlobalConstants.h"
#include "../dependency/debug.h"
#include "../Utils/Timer.h"
#include "../dependency/ExternDefOfGlobalVariables.h"
CreateDatabase::CreateDatabase() {
    // TODO Auto-generated constructor stub

}

CreateDatabase::~CreateDatabase() {
    // TODO Auto-generated destructor stub
}

STATUS_CODE CreateDatabase::run(QueryStructures *queryStruct) {
    
//    Timer start;
//    start.startTimer();
    DEBUG("execute createdatabase" << queryStruct->databaseName);
    BufferManager *bm = BufferManager::getInstance();
    if(isDBOpen == true){
        bm->closeDB();        
    }    

    //create file with specified size
    {
        int err = bm->createDB(queryStruct->databaseName, DEFAULT_NUMBER_PAGES); //Default Number of pages
        if (err != SUCCESS)
            return err;

        err = bm->useDB(queryStruct->databaseName);
        if (err != SUCCESS)
            return err;


        //initialize freelist

        FreePageLinkedList freeLinkedList;
        freeLinkedList.createFreeList(1, DEFAULT_NUMBER_PAGES - 1, PAGE_SIZE);



        //initialize dbmeta data

        char *pgData;
        bm->getPage(0, pgData);

        err = DBMetaData::createHeaderPage(PAGE_SIZE, pgData, 0, DEFAULT_NUMBER_PAGES);
        if (err != SUCCESS)
            return err;
        bm->releasePage(0, true);


        //	err = bm->useDB( executeStructures->databaseName);
        //	if (err != SUCCESS)
        //		return err;
        DBMetaData dbMetaData(0);

        DEBUG("\n=== i aM very oK tILL hERE! === \n ");

        // for systable header page
        DEBUG("******before calling systable********");

        DirHeader sysTableHeaderpage;
        err = sysTableHeaderpage.createDirectoryHeaderPage(); //request for new page


        if (err != SUCCESS)
            return err;

        DEBUG("new page for systab" << sysTableHeaderpage.getPageNo());

        DEBUG("\n====before updating headr pgno alloc  tab" << dbMetaData.toString());

        dbMetaData.updateSysTableHeaderPageNumber(sysTableHeaderpage.getPageNo()); //updating on metadata of db

        DEBUG("\n====AFTER alloc sys tab" << dbMetaData.toString());

        // end of systable header page
        //for creating header for sys column




        DEBUG("******before calling syscol********");
        DirHeader sysColHeaderPage;
        err = sysColHeaderPage.createDirectoryHeaderPage(); //request for new page
        if (err != SUCCESS)
            return err;

        DEBUG("new page for syscol" << sysColHeaderPage.getPageNo());

        DEBUG("\n====before updating headr pgno alloc col tab" << dbMetaData.toString());

        dbMetaData.updateSysColumnsHeaderPageNumber(sysColHeaderPage.getPageNo()); //updating on metadata of db

        DEBUG("\n====AFTER alloc col tab" << dbMetaData.toString());
        // end of sys Col header
        //for creating sys index header


        DEBUG("******before calling sysindex********");
        DirHeader sysIndexHeader;
        err = sysIndexHeader.createDirectoryHeaderPage(); //request for new page
        if (err != SUCCESS)
            return err;
        DEBUG("\n====before updating headr pgno alloc  sys index " << dbMetaData.toString());

        dbMetaData.updateSysIndexHeaderPageNumber(sysIndexHeader.getPageNo()); //updating on metadata of db
        DEBUG("\n====after updating headr pgno alloc  sys index" << dbMetaData.toString());

        //end of sysIndex entry
        // for creating sys col index header

        DEBUG("******before calling sysindexCol********");
        DirHeader sysColIndexHeader;
        err = sysColIndexHeader.createDirectoryHeaderPage(); //request for new page
        if (err != SUCCESS)
            return err;
        DEBUG("\n====before updating headr pgno alloc  sys col index" << dbMetaData.toString());

        dbMetaData.updateSysIndexColumnsHeaderPageNumber(
                sysColIndexHeader.getPageNo()); //updating on metadata of db
        DEBUG("\n====after updating headr pgno alloc  sys col index" << dbMetaData.toString());

        //end of sys col index

        DEBUG("******before calling catalog********");
//
        DEBUG("\n==== before add sys tab record" << dbMetaData.toString());
        SysCatalog sysCatalog;

        sysCatalog.addInitSysTableRecord();
        DEBUG("\n====after add sys tab record" << dbMetaData.toString());
        //DEBUG("******before calling catalog1********");
        sysCatalog.addInitSysColRecord();
        DEBUG("******before calling catalog2********");

        DEBUG("\n====after add sys COL record" << dbMetaData.toString());

        sysCatalog.addInitTableIndexRecord();

        DEBUG("\n====after add sys INDEX record" << dbMetaData.toString());
        //    	
        DEBUG("******before calling catalog3********");
        sysCatalog.addInitTableColIndexRecord();


        DEBUG("\n==== DATABASE CREATED **" << dbMetaData.toString());
    }
    int err = bm->closeDB();
    
//    start.endTimer();
    //start.displayElapsedTimeInMilliSeconds();
    
    if (err != SUCCESS)
        return err;
    return SUCCESS;



}
